﻿using System;
using System.Collections.Generic;
using System.Linq;
using TouchSocket;
using System.Text;
using System.Threading.Tasks;
using TouchSocket.Sockets;
using TouchSocket.Core;


namespace X6TransByBali.Common
{
    public class TouchSocketClient
    {

      
        public TouchSocketClient() { }
        public event Action<string> MsgEvent;

        public event Action<string> ErrEvent;

        TcpClient tcpClient = new TcpClient();
        IWaitingClient<TcpClient> waitClient;

        private bool isStart = false;
        public bool Start(string ip, int port)
        {
            isStart = false;
            tcpClient.Connected += (client, e) => { };//成功连接到服务器
            tcpClient.Disconnected += (client, e) => { this.ShowErr($"与服务器连接断开{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}"); };//从服务器断开连接，当连接不成功时不会触发。
            tcpClient.Received += (client, byteBlock, requestInfo) =>
            {
                //从服务器收到信息
                string mes = Encoding.UTF8.GetString(byteBlock.Buffer, 0, byteBlock.Len);
               // this.ShowMsg($"接收到信息：{mes}");
            };
            tcpClient.Connecting = (client, e) => {
                if (isStart)
                    this.ShowErr($"尝试重新连接{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}");
            };//即将连接到服务器，此时已经创建socket，但是还未建立tcp
            tcpClient.Connected = (client, e) => { this.ShowMsg($"成功连接到服务器{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}"); };//成功连接到服务器
                                                                                //tcpClient.Disconnecting = (client, e) => { return EasyTask.CompletedTask; };//即将从服务器断开连接。此处仅主动断开才有效。
                                                                                //tcpClient.Disconnected = (client, e) => { return EasyTask.CompletedTask; };//从服务器断开连接，当连接不成功时不会触发。

            waitClient = tcpClient.GetWaitingClient(new WaitingOptions()
            {
                AdapterFilter = AdapterFilter.AllAdapter,//表示发送和接收的数据都会经过适配器
                BreakTrigger = true,//表示当连接断开时，会立即触发
                ThrowBreakException = true//表示当连接断开时，是否触发异常

            });

            try
            {

                //声明配置
                TouchSocketConfig config = new TouchSocketConfig();
                config.SetRemoteIPHost(new IPHost($"{ip}:{port}"))
                    .UsePlugin()
                    .SetBufferLength(1024 * 10)
                    .ConfigurePlugins(a =>
                    {
                        a.UseReconnection(-1, true, 1000);
                    });

                //载入配置
                tcpClient.Setup(config);
                tcpClient.Connect(3000);
                isStart = true;
                return true;
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }


        public void SendData(string data)
        {
            if (tcpClient.Online)
                tcpClient.Send(data);
        }

        /// <summary>
        /// TCP发送数据
        /// </summary>
        /// <param name="cmd">发送指令</param>
        /// <param name="timeOut">超时时间毫秒</param>
        /// <returns></returns>
        public string SendMsg(string cmd,int timeOut=3000)
        {
            try
            {
                //同时，如果适配器收到数据后，返回的并不是字节，而是IRequestInfo对象时，可以使用SendThenResponse.
                ResponsedData responsedData = waitClient.SendThenResponse(Encoding.UTF8.GetBytes(cmd), timeOut);
                // IRequestInfo requestInfo = responsedData.Data;//同步收到的RequestInfo
                return Encoding.UTF8.GetString(responsedData.Data);
            }
            catch (Exception)
            {
                return "";
            }

        }

        public bool Connected
        {
            get
            {
                return tcpClient.Online;
            }
        }

        public void Stop()
        {

            tcpClient.Close();
            tcpClient.Dispose();
            GC.SuppressFinalize(tcpClient);
            isStart = false;
        }

        private void ShowMsg(string msg)
        {
            if (MsgEvent != null)
            {
                MsgEvent(msg);
            }

        }

        private void ShowErr(string msg)
        {
            if (ErrEvent != null)
            {
                ErrEvent(msg);
            }

        }

    }
}
